// 真题描述：反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

import { ListNode } from './00-utils';
let l1: any = new ListNode(0);
let cur = l1;
for (let index = 0; index < 5; index++) {
  cur.next = new ListNode(index + 1);
  cur = cur.next;
}
console.log(JSON.stringify(l1));
/**
 * 链表局部反转
 * @param head
 * @param m
 * @param n
 */
const reverseBetween = function (head, m, n) {
  // 定义pre cur leftHead,leftHead用来承接反转部分的前驱结点
  let pre, cur, leftHead;
  // 定义dummy结点
  const dummy = new ListNode();
  // dummy结点指向链表的头结点
  dummy.next = head;
  // 定义p,p是一个游标,最初指向dummy节点,用来遍历
  let p: ListNode | null = dummy;
  // p往前走m-1步,指向待反转部分的前驱结点
  for (let index = 0; index < m - 1; index++) {
    p = p!.next;
  }
  // 缓存这个前驱结点到leftHead里面
  leftHead = p;
  // 创建反转区的第一个节点
  let start = leftHead.next;
  // pre指向start
  pre = start;
  // cur指向start的下一个节点
  cur = start.next;
  // 开始重复反转动作
  for (let i = m; i < n; i++) {
    // 记录下待反转节点的后继节点
    let next = cur.next;
    // 反转节点
    cur.next = pre;
    // pre和cur节点向前一步
    pre = cur;
    cur = next;
  }
  // leftHead 的后继结点此时为反转后的区间的第一个结点
  leftHead.next = pre;
  //  将区间内反转后的最后一个结点 next 指向 cur
  start.next = cur;
  // dummy.next 永远指向链表头结点
  return dummy.next;
};
